#include <time.h>
#include "utils.hpp"
#include "agent.hpp"

// 全局总代价
double Global_Fit(Agent* agent, uint32_t tsk) {
    double cost = 0;
    for (int i = 0; i < N; i++)
        cost += agent[i].ccost;
    cost += UNCOVER_WEIGHT * CountSetBits(tsk ^ ((1<<M) - 1));
    return cost;
}

int main() {
    srand(time(0));
    Mat matC = read_csv("../data/matC.csv");  // 卫星执行任务载荷能量消耗矩阵 0表示无法执行该任务
    Mat matD = read_csv("../data/matD.csv");  // 卫星执行任务侧摆角度 0表示无法执行该任务
    Mat matFT = read_csv("../data/matFT.csv");  // 需要执行的任务数量，和每个任务的编号
    Mat matNeighbor = read_csv("../data/matNeighbor.csv");  // 每个卫星的邻居数量，和每个邻居的编号
    Agent stlt[N];  // N个卫星(satellite)
    Mat matdata;  // 临时数据
    int intdata;  // 临时数据
    for (int i = 0; i < N; i++) {  // 初始化
        stlt[i].id = i;
        stlt[i].matC = matC.atr(i).T();
        stlt[i].matD = matD.atr(i).T();
        for (int j = 0; j < matNeighbor.at(i, 0); j++)  // 每行的第一列(i,0)为邻居数量
            stlt[i].neighbor |= (1 << uint32_t(N - matNeighbor.at(i, j+1)));  // 将邻居存入
        for (int j = 0; j < matFT.at(i, 0); j++)  // 每行的第一列(i,0)为可行任务数量
            stlt[i].feasibleTask |= 1 << uint32_t(M - (matFT.at(i, j+1)));  // 将任务存入
        matdata = read_csv("../data/matJointF" + to_string(i+1) + ".csv");  // 每个卫星的策略集
        for (int j = 0; j < matdata.row(); j++)  // 每一行为一个策略
            if (matdata.at(j, matdata.col()-2) == 1)  // 倒数第2列为策略是否可用的标志
                stlt[i].feasibleStrategy.push_back(j);  // 将可用的策略编号存入
        stlt[i].Init();
    }
    matC.Clear(); matD.Clear(); matFT.Clear(); matNeighbor.Clear();

// 因为代码中有随机数，下面这段没有缩进的代码读取了原作者代码的某次初始策略，用于与原代码的结果相比较
Mat S=read_csv("C:/temp/test.csv");
for (size_t i = 0; i < 5; i++) {
    stlt[i].csid=stlt[i].TotalStrategy_to_SID(S.atr(i).T());
    stlt[i].cstrategy = stlt[i].SID_to_ImplementStrategy(stlt[i].csid);
}

    uint32_t task;  // 一组任务的标志位
    uint32_t ims;  // 执行策略
    double cost, cost1, cost2;  // 总收益，执行了任务的收益，个体的代价
    double maxvalue; uint32_t maxvaluei;  // 最大值和最大值索引
    uint32_t NE;  // 达到纳什均衡的个体数量
    for (int t = 0; t < TMAX; t++) {  // 分布式协调
        NE = 0;
        for (int i = 0; i < N; i++) {  // 每个个体计算当前最优策略
            task = 0;
            for (int j = 0; j < N; j++)  // 计算个体的所有邻居执行策略后的未覆盖任务
                if (stlt[i].neighbor & (1 << (N-1-j)))  // 是当前个体的邻居
                    task |= stlt[j].cstrategy;  // 每个邻居个体依次执行自己的策略并更新任务标志位
            task ^= (1<<M) - 1;  // 将任务标志位取反表示尚未执行的任务
            task &= stlt[i].feasibleTask;  // 尚未执行并且可以由当前个体执行的任务
            maxvalue = 0;
            if (task) {  // 当存在可执行的任务时，求当前最优策略
                for (uint32_t j: stlt[i].feasibleStrategy) {  // 在可执行任务中选择收益最大的任务
                    ims = stlt[i].SID_to_ImplementStrategy(j);  // 根据策略编号计算执行策略
                    cost1 = UNCOVER_WEIGHT * CountSetBits(task & ims);  // 执行了任务的收益
                    cost2 = stlt[i].Strategy_Cost(ims);  // 个体的代价
                    cost = cost1 - cost2;  // 每个策略的总收益
                    if (cost > maxvalue)  // 求最优策略的代价值和编号
                        { maxvalue = cost; maxvaluei = j; }
                }
                stlt[i].bestsid = maxvaluei;  // 局部最优策略
            }
            else  // 当没有可执行的任务时，最优策略为0
                stlt[i].bestsid = 0;
            cost1 = UNCOVER_WEIGHT * CountSetBits(task & stlt[i].cstrategy);
            cost2 = stlt[i].Strategy_Cost(stlt[i].cstrategy);
            cost = cost1 - cost2;  // 计算当前策略的收益
            stlt[i].regret = maxvalue - cost;  // 计算遗憾值
            if (stlt[i].regret == 0)  // 遗憾值为0表示达到纳什均衡
                NE++;
            else if (stlt[i].regret < 0)
                cout << "regret error!" << endl;
        }
        maxvalue = 0;
        for (int i = 0; i < N; i++) {  // 计算所有个体中的最大遗憾值
            if (stlt[i].regret > maxvalue)
                { maxvalue = stlt[i].regret; maxvaluei = i; }
        }
        for (int i = 0; i < N; i++) {  // 每个个体更新策略
            if (maxvalue == 0)
                stlt[i].nsid = stlt[i].csid;
            else if (i == maxvaluei)
                stlt[i].nsid = stlt[i].bestsid;
            else
                stlt[i].nsid = stlt[i].csid;
            stlt[i].Update();
        }
        if (NE == N)  // 所有个体都达到了纳什均衡
            break;
    }
    task = 0;
    for (int j = 0; j < N; j++) {
        ims = stlt[j].SID_to_ImplementStrategy(stlt[j].nsid);
        stlt[j].ccost = stlt[j].Strategy_Cost(ims);
        task |= ims;
    }
    cout << Global_Fit(stlt, task) << endl;
    for (int i = 0; i < N; i++)
        cout << stlt[i].nsid << endl;
    return 0;
}
